// SPDX-License-Identifier: Mulan PSL v2
/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * This software is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

use super::*;

/// Performs a generic round-trip test for any type that implements the `Framer` trait.
/// It encodes a payload, decodes it, and verifies that the result matches the original.
fn round_trip_test<F: Framer>(framer: F, original_payload: &[u8]) {
    // The buffer size is dynamically calculated based on the framer's header length.
    let mut encode_buffer = vec![0u8; framer.header_len() + original_payload.len() + 16];

    let payload_len = original_payload.len();

    // 1. Prepare buffer
    let (header, payload) = framer.prepare_buffer(&mut encode_buffer).unwrap();

    // 2. Write payload
    let payload = &mut payload[..payload_len];
    payload.copy_from_slice(original_payload);

    // 3. Encode frame
    let frame_len = framer.encode_frame(header, payload).unwrap();

    // 4. Decode frame
    let decode_buffer = &encode_buffer[..frame_len];
    let (consumed, decoded_payload) = framer.decode_frame(decode_buffer).unwrap().unwrap();

    // 5. Verify
    let expected_len = framer.header_len() + payload_len;
    assert_eq!(
        frame_len, expected_len,
        "Total written bytes should be header_len + payload_len"
    );
    assert_eq!(
        consumed, expected_len,
        "Consumed bytes should equal the total frame length"
    );
    assert_eq!(
        decoded_payload, original_payload,
        "Decoded payload must match the original payload"
    );
}

mod generic_framer {
    use super::*;

    #[test]
    fn round_trip_standard_payload() {
        round_trip_test(GenericFramer::default(), b"Hello, GenericFramer!");
    }

    #[test]
    fn round_trip_empty_payload() {
        round_trip_test(GenericFramer::default(), b"");
    }

    #[test]
    fn round_trip_single_byte_payload() {
        round_trip_test(GenericFramer::default(), b"\x42");
    }
}

mod raw_framer {
    use super::*;

    #[test]
    fn round_trip_standard_payload() {
        round_trip_test(RawFramer::default(), b"This is a raw payload.");
    }

    #[test]
    fn round_trip_empty_payload() {
        round_trip_test(RawFramer::default(), b"");
    }

    #[test]
    fn round_trip_single_byte_payload() {
        round_trip_test(RawFramer::default(), b"\xFF");
    }
}
